home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Source Code / Zoners Half-Life Tools / template / ReferenceCounter.h < prev    next >
C/C++ Source or Header  |  2001-04-18  |  6KB  |  234 lines

  1. // Copyright (C) 2000  Sean Cavanaugh
  2. // This file is licensed under the terms of the Lesser GNU Public License
  3. // (see LPGL.txt, or http://www.gnu.org/copyleft/lesser.txt)
  4.  
  5. #ifndef ReferenceCounter_H__
  6. #define ReferenceCounter_H__
  7.  
  8. #if _MSC_VER > 1000
  9. #pragma once
  10. #endif // _MSC_VER > 1000
  11.  
  12. #ifdef _WIN32
  13. #define WIN32_LEAN_AND_MEAN
  14. #include <windows.h>
  15. #endif
  16.  
  17. #ifdef HAVE_SYS_ATOMIC_H
  18. #include <sys/atomic.h>
  19. #endif
  20.  
  21. #ifdef HAVE_ASM_ATOMIC_H
  22. #include <asm/atomic.h>
  23. #endif
  24.  
  25. /*!
  26.   \author  Sean Cavanaugh
  27.   \email   sean@dimensionalrift.com
  28.   \cvsauthor $Author: sean $
  29.   \date    $Date: 2000/09/11 20:28:24 $
  30.   \version $Revision: 1.1 $
  31.   \brief   ReferenceCounter abstracts a reference counted integer with proper thread safe access
  32.            The interface is not platform specific in any way, except the protected data
  33.            is platform specific, as well as the implementation details
  34. */
  35.  
  36. class ReferenceCounter
  37. {
  38. // Construction
  39. public:
  40.     ReferenceCounter();
  41.     ReferenceCounter(int InitialValue);
  42.     virtual ~ReferenceCounter() {} // Should optimize to nothing except in the derived-class case
  43.     ReferenceCounter(const ReferenceCounter& other) {copy(other);}
  44.     ReferenceCounter& operator=(const ReferenceCounter& other) {copy(other); return *this;}
  45.  
  46. public:
  47.     // User functions 
  48.     inline int add(int amt);// increment the value by amt, returns the ORIGINAL value
  49.     inline int sub(int amt);// increment the value by amt, returns the ORIGINAL value
  50.     inline int inc();// increment the value, returns the NEW value
  51.     inline int dec();// decrement the value, returns the NEW value
  52.     inline int read() const;// read the current value
  53.     inline void write(int newvalue);// change the counter to a new value blindly
  54.     inline int swap(int newvalue);// change the counter to a new value, and return the ORIGINAL value
  55.  
  56.     // Convenient Operators
  57.     int operator++() {return inc();}
  58.     int operator--() {return dec();}
  59.     int operator++(int) {return inc() - 1;}
  60.     int operator--(int) {return dec() + 1;}
  61.     int operator+=(int amt) {return add(amt) + amt;}
  62.     int operator-=(int amt) {return sub(amt) - amt;}
  63.     int operator=(int value) {write(value); return value;}
  64.     operator int() const {return read();}
  65.  
  66. // Internal Methods
  67. protected:
  68.     inline void copy(const ReferenceCounter& other);
  69.  
  70. // Data
  71. protected:
  72. #ifdef  SINGLE_THREADED
  73.     int m_atom;
  74. #else //SINGLE_THREADED
  75.  
  76. #ifdef _WIN32
  77.     long m_atom;
  78. #endif
  79. #ifdef HAVE_ATOMIC
  80.     atomic_t m_atom;
  81. #endif
  82.  
  83. #endif//SINGLE_THREADED
  84. };
  85.  
  86.  
  87. #ifdef SINGLE_THREADED
  88. inline ReferenceCounter::ReferenceCounter()
  89. {
  90.     m_atom = 0;
  91. }
  92. inline ReferenceCounter::ReferenceCounter(int InitialValue)
  93. {
  94.     m_atom = InitialValue;
  95. }
  96. inline int ReferenceCounter::add(int amt)
  97. {
  98.     m_atom += amt;
  99.     return m_atom;
  100. }
  101. inline int ReferenceCounter::sub(int amt)
  102. {
  103.     m_atom -= amt;
  104.     return m_atom;
  105. }
  106. inline int ReferenceCounter::inc()
  107. {
  108.     m_atom++;
  109.     return m_atom;
  110. }
  111. inline int ReferenceCounter::dec()
  112. {
  113.     m_atom--;
  114.     return m_atom;
  115. }
  116. inline int ReferenceCounter::swap(int newvalue)
  117. {
  118.     int rval = m_atom;
  119.     m_atom = newvalue;
  120.     return rval;
  121. }
  122. inline void ReferenceCounter::write(int newvalue)
  123. {
  124.     m_atom = newvalue;
  125. }
  126. inline int ReferenceCounter::read() const
  127. {
  128.     return m_atom;
  129. }
  130. inline void ReferenceCounter::copy(const ReferenceCounter& other)
  131. {
  132.     m_atom = other.m_atom;
  133. }
  134. #else // SINGLE_THREADED
  135.  
  136. #ifdef _WIN32
  137. inline ReferenceCounter::ReferenceCounter()
  138. {
  139.     m_atom = 0;
  140. }
  141. inline ReferenceCounter::ReferenceCounter(int InitialValue)
  142. {
  143.     m_atom = InitialValue;
  144. }
  145. inline int ReferenceCounter::add(int amt)
  146. {
  147.     return InterlockedExchangeAdd(&m_atom, amt);
  148. }
  149. inline int ReferenceCounter::sub(int amt)
  150. {
  151.     return InterlockedExchangeAdd(&m_atom, -amt);
  152. }
  153. inline int ReferenceCounter::inc()
  154. {
  155.     return InterlockedIncrement(&m_atom);
  156. }
  157. inline int ReferenceCounter::dec()
  158. {
  159.     return InterlockedDecrement(&m_atom);
  160. }
  161. inline int ReferenceCounter::swap(int newvalue)
  162. {
  163.     return InterlockedExchange(&m_atom, newvalue);
  164. }
  165. inline void ReferenceCounter::write(int newvalue)
  166. {
  167.     InterlockedExchange(&m_atom, newvalue);
  168. }
  169. inline int ReferenceCounter::read() const
  170. {
  171.     return m_atom;
  172. }
  173. inline void ReferenceCounter::copy(const ReferenceCounter& other)
  174. {
  175.     m_atom = other.m_atom;
  176. }
  177. #endif//_WIN32
  178.  
  179. #ifdef HAVE_ATOMIC
  180. inline ReferenceCounter::ReferenceCounter()
  181. {
  182.     m_atom.counter = 0;
  183. }
  184. inline ReferenceCounter::ReferenceCounter(int InitialValue)
  185. {
  186.     m_atom.counter = InitialValue;
  187. }
  188. inline int ReferenceCounter::add(int amt)
  189. {
  190.     int rval = atomic_read(&m_atom);
  191.     atomic_add(amt, &m_atom);
  192.     return rval;
  193. }
  194. inline int ReferenceCounter::sub(int amt)
  195. {
  196.     int rval = atomic_read(&m_atom);
  197.     atomic_sub(amt, &m_atom);
  198.     return rval;
  199. }
  200. inline int ReferenceCounter::inc()
  201. {
  202.     int rval = atomic_read(&m_atom);
  203.     atomic_inc(&m_atom);
  204.     return rval + 1;
  205. }
  206. inline int ReferenceCounter::dec()
  207. {
  208.     int rval = atomic_read(&m_atom);
  209.     atomic_dec(&m_atom);
  210.     return rval - 1;
  211. }
  212. inline int ReferenceCounter::swap(int newvalue)
  213. {
  214.     int rval = atomic_read(&m_atom);
  215.     atomic_set(&m_atom, newvalue);
  216.     return rval;
  217. }
  218. inline void ReferenceCounter::write(int newvalue)
  219. {
  220.     atomic_set(&m_atom, newvalue);
  221. }
  222. inline int ReferenceCounter::read() const
  223. {
  224.     return atomic_read(&m_atom);
  225. }
  226. inline void ReferenceCounter::copy(const ReferenceCounter& other)
  227. {
  228.     m_atom.counter = other.read();
  229. }     
  230. #endif//HAVE_ATOMIC
  231. #endif//SINGLE_THREADED
  232.  
  233. #endif//ReferenceCounter_H__
  234.